/*******************************************************************
 * author   :  Charlies-ls
 * Date     :  2021-09-26
 * Copyright (c) 2021. artestplay@outlook.com. All Rights Reserved.
 *******************************************************************/
#include "ax_thread_fifo.h"
#include "com.h"
#include "ax_printf.h"
#include "ax_time.h"

ax_thread_fifo* ax_thread_fifo_create()
{
    ax_thread_fifo* q = ALLOC(ax_thread_fifo);
    q->mutex        = ax_mutex_create();
    q->fifo         = ax_fifo_create();
    q->write_signal = ax_cond_create();
    q->read_signal  = ax_cond_create();
    return q;
}

void ax_thread_fifo_destory(ax_thread_fifo*q)
{
    ax_check_and_return(q, "empty");
    ax_fifo_destory(q->fifo);
    ax_mutex_destroy(q->mutex);
    ax_cond_destroy(q->read_signal);
    ax_cond_destroy(q->write_signal);
    free(q);
}

int ax_thread_fifo_size(ax_thread_fifo *fifo)
{
    ax_check_and_return_zero(fifo, "empty");
    return ax_fifo_size(fifo->fifo);
}

/**
 * @brief ax_thread_fifo_write
 *        写入指针
 * @param queue
 * @param data
 */
void ax_thread_fifo_write(ax_thread_fifo*queue,void* data)
{
    ax_check_and_return(queue && data, "error");
    ax_mutex_lock(queue->mutex);
    ax_fifo_push(queue->fifo,data);
    ax_mutex_unlock(queue->mutex);
    ax_cond_signal(queue->write_signal);
}

/**
 * @brief ax_thread_fifo_read
 *        阻塞读取数据,一直等待直到有数据，
 *        一旦有数据，返回数据的指针，同时从fifo中删除数据节点
 * @param queue
 * @return 返回数据的指针
 */
void* ax_thread_fifo_read(ax_thread_fifo*queue)
{
    ax_check_and_return_zero(queue, "error");
    ax_mutex_lock(queue->mutex);
    void* ret= NULL;
    while(ax_thread_fifo_size(queue) == 0)
    {
        ax_cond_wait(queue->write_signal, queue->mutex);
        if(ax_thread_fifo_size(queue)>0)
        {
            break;
        }
    }
    ret = ax_fifo_pop(queue->fifo);
    ax_cond_signal(queue->read_signal);
    ax_mutex_unlock(queue->mutex);
    return ret;
}

/**
 * @brief ax_thread_fifo_read_timeout
 ×        超时读取,同时在fifo中删除节点
 * @param queue
 * @param timeout  ms
 * @return 超时为0,否则返回数据的指针
 */
void* ax_thread_fifo_read_timeout(ax_thread_fifo*queue,int timeout)
{
    if(0 == timeout)
        return ax_thread_fifo_read_noblock(queue);

    int time_end = ax_timestamp() + timeout;
    ax_mutex_lock(queue->mutex);
    void* ret=0;
    while(ax_thread_fifo_size(queue)==0)
    {
        int remaind = time_end - ax_timestamp();
        if(remaind<2)
        {
            break;
        }
        ax_cond_wait_timeout_ms(queue->write_signal, queue->mutex,remaind);
    }
    if(ax_thread_fifo_size(queue) > 0)
    {
        ret = ax_fifo_pop(queue->fifo);
        ax_cond_signal(queue->read_signal);
    }
    ax_mutex_unlock(queue->mutex);
    return ret;
}

/**
 * @brief ax_thread_fifo_read_noblock
 *        直接读取数据
 * @param queue
 * @return 0或数据的指针
 */
void* ax_thread_fifo_read_noblock(ax_thread_fifo*queue)
{
    ax_check_and_return_zero(queue, "error");
    ax_mutex_lock(queue->mutex);
    void* ret=0;
    if(ax_thread_fifo_size(queue) == 0)
        ret = 0;
    else
    {
        ret = ax_fifo_pop(queue->fifo);
        ax_cond_signal(queue->read_signal);
    }
    ax_mutex_unlock(queue->mutex);
    return ret;
}

/**
 * @brief ax_thread_fifo_front
 *        获取首部的节点
 * @param queue
 * @return
 */
void* ax_thread_fifo_front(ax_thread_fifo*queue)
{
    ax_check_and_return_zero(queue, "empty");
    return ax_fifo_front(queue->fifo);
}
